import 'dart:async';
import 'dart:io';
import 'package:audio_waveforms/audio_waveforms.dart';
import 'package:flutter/material.dart';
import 'package:flutter_easyloading/flutter_easyloading.dart';
import 'package:path_provider/path_provider.dart';
import 'package:permission_handler/permission_handler.dart';

import '../models/bt_chat_model.dart';

class BtChatVoiceHoldWidget extends StatefulWidget {
  const BtChatVoiceHoldWidget({super.key, required this.model});

  final BtChatModel model;

  @override
  State createState() => _BtChatVoiceHoldState();
}

class _BtChatVoiceHoldState extends State<BtChatVoiceHoldWidget> {
  int? duration = 4;
  bool enableVoidRecording = false;
  late final RecorderController recorderController;
  String? path;
  String? musicFile;
  bool isRecording = false;
  bool isRecordingCompleted = false;
  bool isLoading = true;
  late Directory appDirectory;
  var isEnd = false;
  bool _recordCanSend = false;
  Timer? timer;

  set recordCanSend(bool value) {
    if (_recordCanSend != value) {
      _recordCanSend = value;
    }
  }

  bool isRecordCanSend(recordDragOffset) {
    if (recordDragOffset == null) {
      return false;
    }
    return recordDragOffset! > MediaQuery.of(context).size.height - 140;
  }

  @override
  void initState() {
    super.initState();
    _getDir();
    _initialiseControllers();
  }

  void _getDir() async {
    appDirectory = await getTemporaryDirectory();
    path = "${appDirectory.path}/recording.m4a";
    isLoading = false;
    setState(() {});
  }

  void _initialiseControllers() {
    recorderController = RecorderController()
      ..androidEncoder = AndroidEncoder.aac
      ..androidOutputFormat = AndroidOutputFormat.mpeg4
      ..iosEncoder = IosEncoder.kAudioFormatMPEG4AAC
      ..sampleRate = 44100;
  }

  void record() async {
    if (!await Permission.microphone.isGranted) {
      var permissionStatus = await Permission.microphone.request();
      if (permissionStatus != PermissionStatus.granted) {
        EasyLoading.showToast("You have not authorised this permission.");
        return;
      }
    }
    isEnd = true;
    recorderController.record(path: path);
    timer?.cancel();
    timer = Timer(const Duration(seconds: 60), () {
      if (mounted) {
        end();
      }
    });
  }

  void stopRecorder() async {
    if (!isEnd) {
      return;
    }
    isEnd = false;
    if (recorderController.isRecording == false) {
      return;
    }
    var path = await recorderController.stop();
    var recordedDuration = recorderController.recordedDuration.inSeconds;
    if (recordedDuration < 1) {
      EasyLoading.showToast("Recordings can't be less than 1 second.");
      return;
    }

    widget.model.sendVoiceMessage(path, recordedDuration);
  }

  end() {
    enableVoidRecording = false;
    widget.model.setVoiceRecording(null);
    if (!_recordCanSend) {
      return;
    }
    stopRecorder();
  }

  @override
  Widget build(BuildContext context) {
    return GestureDetector(
      onTapDown: (detail) {
        enableVoidRecording = true;
        recordCanSend = isRecordCanSend(detail.globalPosition.dy);
        widget.model.setVoiceRecording(_recordCanSend);

        record();
      },
      onVerticalDragUpdate: (detail) {
        if (!enableVoidRecording) {
          return;
        }
        recordCanSend = isRecordCanSend(detail.globalPosition.dy);
        widget.model.setVoiceRecording(_recordCanSend);
      },
      onTapUp: (detail) {
        end();
      },
      onVerticalDragCancel: () {
        end();
      },
      onVerticalDragEnd: (detail) {
        end();
      },
      child: Container(
        width: MediaQuery.of(context).size.width - 126,
        height: 36,
        padding: const EdgeInsets.only(top: 8),
        decoration: BoxDecoration(
          color: const Color(0xFFFFFFFF),
          borderRadius: BorderRadius.circular(8),
        ),
        child: const Text(
          'Hold to talk',
          textAlign: TextAlign.center,
          style: TextStyle(
            fontSize: 12,
            color: Color(0xFF4DB4FF),
          ),
        ),
      ),
    );
  }

  @override
  void dispose() {
    recorderController.dispose();
    timer?.cancel();
    super.dispose();
  }
}
